package co.yixiang.yshop.module.store.service.storewithdrawal;

import co.yixiang.yshop.framework.common.exception.ErrorCode;
import co.yixiang.yshop.module.store.controller.admin.userbank.vo.UserBankBaseVO;
import co.yixiang.yshop.module.store.controller.admin.userbank.vo.UserBankRespVO;
import co.yixiang.yshop.module.store.convert.userbank.UserBankConvert;
import co.yixiang.yshop.module.store.dal.dataobject.storeshop.StoreShopDO;
import co.yixiang.yshop.module.store.dal.dataobject.userbank.UserBankDO;
import co.yixiang.yshop.module.store.dal.mysql.storeshop.StoreShopMapper;
import co.yixiang.yshop.module.store.dal.mysql.userbank.UserBankMapper;
import co.yixiang.yshop.module.store.enums.WithdrawalStatusEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.util.*;
import co.yixiang.yshop.module.store.controller.admin.storewithdrawal.vo.*;
import co.yixiang.yshop.module.store.dal.dataobject.storewithdrawal.StoreWithdrawalDO;
import co.yixiang.yshop.framework.common.pojo.PageResult;

import co.yixiang.yshop.module.store.convert.storewithdrawal.StoreWithdrawalConvert;
import co.yixiang.yshop.module.store.dal.mysql.storewithdrawal.StoreWithdrawalMapper;

import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.module.store.enums.ErrorCodeConstants.*;

/**
 * 提现管理 Service 实现类
 *
 * @author yshop
 */
@Service
@Validated
public class StoreWithdrawalServiceImpl implements StoreWithdrawalService {

    @Resource
    private StoreWithdrawalMapper withdrawalMapper;
    @Resource
    private StoreShopMapper shopMapper;
    @Resource
    private UserBankMapper userBankMapper;

    @Override
    public Long createWithdrawal(StoreWithdrawalCreateReqVO createReqVO) {
        // 插入
        StoreWithdrawalDO withdrawal = StoreWithdrawalConvert.INSTANCE.convert(createReqVO);
        StoreShopDO storeShopDO = this.getShop(createReqVO.getShopId());
        this.check(withdrawal,storeShopDO);
        withdrawal.setShopName(storeShopDO.getName());
        withdrawalMapper.insert(withdrawal);
        // 返回
        return withdrawal.getId();
    }

    @Override
    public void updateWithdrawal(StoreWithdrawalUpdateReqVO updateReqVO) {
        // 校验存在
        validateWithdrawalExists(updateReqVO.getId());
        // 更新
        StoreWithdrawalDO updateObj = StoreWithdrawalConvert.INSTANCE.convert(updateReqVO);
        StoreShopDO storeShopDO = this.getShop(updateObj.getShopId());
        if(updateReqVO.getIsCheck()) {
            if(WithdrawalStatusEnum.STATUS_2.getValue().equals(updateReqVO.getStatus())){
                //店铺金额加回去
                BigDecimal newBalance = storeShopDO.getBalance().add(updateObj.getAmount());
                storeShopDO.setBalance(newBalance);
                shopMapper.updateById(storeShopDO);
            }
        }else {
            this.check(updateObj,storeShopDO);
        }

        updateObj.setShopName(storeShopDO.getName());
        withdrawalMapper.updateById(updateObj);
    }

    @Override
    public void deleteWithdrawal(Long id) {
        // 校验存在
        validateWithdrawalExists(id);
        // 删除
        withdrawalMapper.deleteById(id);
    }

    private void validateWithdrawalExists(Long id) {
        if (withdrawalMapper.selectById(id) == null) {
            throw exception(WITHDRAWAL_NOT_EXISTS);
        }
    }

    @Override
    public StoreWithdrawalRespVO getWithdrawal(Long id) {
        StoreWithdrawalRespVO storeWithdrawalRespVO = StoreWithdrawalConvert.INSTANCE.convert(withdrawalMapper.selectById(id));
        UserBankDO userBankDO = userBankMapper.selectById(storeWithdrawalRespVO.getBankId());
        UserBankRespVO userBankRespVO = UserBankConvert.INSTANCE.convert(userBankDO);
        storeWithdrawalRespVO.setUserBank(userBankRespVO);
        return storeWithdrawalRespVO;
    }

    @Override
    public List<StoreWithdrawalDO> getWithdrawalList(Collection<Long> ids) {
        return withdrawalMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<StoreWithdrawalRespVO> getWithdrawalPage(StoreWithdrawalPageReqVO pageReqVO) {
        PageResult<StoreWithdrawalDO> pageResult =  withdrawalMapper.selectPage(pageReqVO);
        PageResult<StoreWithdrawalRespVO> storeWithdrawalRespVOPageResult =  StoreWithdrawalConvert.INSTANCE.convertPage(pageResult);
        for (StoreWithdrawalRespVO storeWithdrawalRespVO : storeWithdrawalRespVOPageResult.getList()) {
            UserBankDO userBankDO = userBankMapper.selectById(storeWithdrawalRespVO.getBankId());
            UserBankRespVO userBankRespVO = UserBankConvert.INSTANCE.convert(userBankDO);
            storeWithdrawalRespVO.setUserBank(userBankRespVO);
        }
        return storeWithdrawalRespVOPageResult;
    }

    @Override
    public List<StoreWithdrawalDO> getWithdrawalList(StoreWithdrawalExportReqVO exportReqVO) {
        return withdrawalMapper.selectList(exportReqVO);
    }


    /**
     * 获取门店
     * @param id
     * @return
     */
    private StoreShopDO getShop(Long id){
        //查找门店
        StoreShopDO storeShopDO = shopMapper.selectById(id);
        return  storeShopDO;
    }

    private void check(StoreWithdrawalDO withdrawal,StoreShopDO storeShopDO){
        //return;
        Long count =  withdrawalMapper.selectCount(new LambdaQueryWrapper<StoreWithdrawalDO>()
                .eq(StoreWithdrawalDO::getShopId,storeShopDO.getId()).le(StoreWithdrawalDO::getStatus,1));
        if(count > 0){
            throw exception(new ErrorCode(1008016007, "清等待上次提现结果审核"));
        }
        if(BigDecimal.ZERO.compareTo(withdrawal.getAmount()) >= 0){
            throw exception(new ErrorCode(1008016005, "提现金额必须大于0"));
        }
        if(withdrawal.getAmount().compareTo(storeShopDO.getBalance()) > 0) {
            throw exception(new ErrorCode(1008016006, "提现金额超额"));
        }

        //店铺金额减少
        BigDecimal newBalance = storeShopDO.getBalance().subtract(withdrawal.getAmount());
        storeShopDO.setBalance(newBalance);
        shopMapper.updateById(storeShopDO);

    }

}
